package com.example.demo.controller;

import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.*;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;

@Slf4j
@RestController
@RequestMapping("askForLeave")
public class AskForLeaveFlowableController {
	@Autowired
	private RuntimeService runtimeService;
	@Autowired
	private TaskService taskService;
	@Autowired
	private RepositoryService repositoryService;
	@Autowired
	private ProcessEngine processEngine;

	@PostConstruct
	public void init(){
		// 1.获取 RepositoryService
		RepositoryService repositoryService = processEngine.getRepositoryService();
		// 2.完成流程的部署操作
		Deployment deploy = repositoryService.createDeployment()
				.addClasspathResource("test.bpmn20.xml")
				.name("请假流程")
				.deploy();
		System.out.println("deploy.getId() = " + deploy.getId());
		System.out.println("deploy.getName() = " + deploy.getName());
	}

	/**
	 * 员工提交请假申请
	 *
	 * @param employeeNo 员工工号
	 * @param name       姓名
	 * @param reason     原因
	 * @param days       天数
	 * @return
	 */
	@GetMapping("employeeSubmit")
	public String employeeSubmitAskForLeave(
			@RequestParam(value = "employeeNo") String employeeNo,
			@RequestParam(value = "name") String name,
			@RequestParam(value = "reason") String reason,
			@RequestParam(value = "days") Integer days) {
		HashMap<String, Object> map = new HashMap<>();
		/**
		 * 员工编号字段来自于配置文件
		 */
		map.put("employeeNo", employeeNo);
		map.put("name", name);
		map.put("reason", reason);
		map.put("days", days);
		/**
		 *      key：配置文件中的下个处理流程id
		 *      value：默认领导工号为002
		 */
		map.put("leaderNo", "002");

		/**
		 * askForLeave：为开启流程的id  与配置文件中的一致
		 */
		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("askForLeave", map);
		log.info("{},提交请假申请，流程id：{}", name, processInstance.getId());
		return "提交成功，流程id："+processInstance.getId();
	}

	/**
	 * 领导审核通过
	 * @param employeeNo  员工工号
	 * @return
	 */
	@GetMapping("leaderExaminePass")
	public String leaderExamine(@RequestParam(value = "employeeNo") String employeeNo) {
		List<Task> taskList = taskService.createTaskQuery().taskAssignee(employeeNo).orderByTaskId().desc().list();
		if (null == taskList) {
			throw  new RuntimeException("当前员工没有任何申请");
		}
		for (Task task : taskList) {
			if (task == null) {
				log.info("任务不存在 ID：{}；", task.getId());
				continue;
			}
			log.info("任务 ID：{}；任务处理人：{}；任务是否挂起：{}", task.getId(), task.getAssignee(), task.isSuspended());
			Map<String, Object> map = new HashMap<>();
			/**
			 *      key：配置文件中的下个处理流程id
			 *      value：默认老板工号为001
			 */
			map.put("bossNo", "001");
			/**
			 *      key：指定配置文件中的条件判断id
			 *      value：指定配置文件中的审核条件
			 */
			map.put("outcome", "通过");
			taskService.complete(task.getId(), map);
		}
		return "领导审核通过";
	}


	/**
	 * 老板审核通过
	 * @param leaderNo  领导工号
	 * @return
	 */
	@GetMapping("bossExaminePass")
	public String bossExamine(@RequestParam(value = "leaderNo") String leaderNo) {
		List<Task> taskList = taskService.createTaskQuery().taskAssignee(leaderNo).orderByTaskId().desc().list();
		if (null == taskList) {
			throw  new RuntimeException("当前员工没有任何申请");
		}
		for (Task task : taskList) {
			if (task == null) {
				log.info("任务不存在 ID：{}；", task.getId());
				continue;
			}
			log.info("任务 ID：{}；任务处理人：{}；任务是否挂起：{}", task.getId(), task.getAssignee(), task.isSuspended());
			Map<String, Object> map = new HashMap<>();
			/**
			 *     老板是最后的审批人   无需指定下个流程
			 */
//            map.put("boss", "001");
			/**
			 *      key：指定配置文件中的条件判断id
			 *      value：指定配置文件中的审核条件
			 */
			map.put("outcome", "通过");
			taskService.complete(task.getId(), map);
		}
		return "领导审核通过";
	}

	/**
	 * 驳回
	 *
	 * @param employeeNo  员工工号
	 * @return
	 */
	@GetMapping("reject")
	public String reject(@RequestParam(value = "employeeNo") String employeeNo) {
		List<Task> taskList = taskService.createTaskQuery().taskAssignee(employeeNo).orderByTaskId().desc().list();
		if (null == taskList) {
			throw  new RuntimeException("当前员工没有任何申请");
		}
		for (Task task : taskList) {
			if (task == null) {
				log.info("任务不存在 ID：{}；", task.getId());
				continue;
			}
			log.info("任务 ID：{}；任务处理人：{}；任务是否挂起：{}", task.getId(), task.getAssignee(), task.isSuspended());
			Map<String, Object> map = new HashMap<>();
			/**
			 *      key：指定配置文件中的领导id
			 *      value：指定配置文件中的审核条件
			 */
			map.put("outcome", "驳回");
			taskService.complete(task.getId(), map);
		}
		return "申请被驳回";
	}

	/**
	 * 驳回
	 *
	 * @param employeeNo 员工工号
	 * @return
	 */
	@GetMapping("list")
	public List<Task> list(@RequestParam(value = "list") String employeeNo) {
		//taskCandidateUser() 根据指定人查
		//taskCandidateGroup() 根据指定组查
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		TaskService taskService = processEngine.getTaskService();
		List<Task> list = taskService.createTaskQuery().taskAssignee(employeeNo).orderByTaskCreateTime().desc().list();
		List<Task> list1 = taskService.createTaskQuery().includeCaseVariables().list();

		return list;
	}


	/**
	 * 生成流程图
	 *
	 * @param processId 任务ID
	 */
	@GetMapping(value = "processDiagram")
	public void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) throws Exception {
		ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();

		//流程走完的不显示图
		if (pi == null) {
			return;
		}
		Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
		//使用流程实例ID，查询正在执行的执行对象表，返回流程实例对象
		String InstanceId = task.getProcessInstanceId();
		List<Execution> executions = runtimeService
				.createExecutionQuery()
				.processInstanceId(InstanceId)
				.list();

		//得到正在执行的Activity的Id
		List<String> activityIds = new ArrayList<>();
		List<String> flows = new ArrayList<>();
		for (Execution exe : executions) {
			List<String> ids = runtimeService.getActiveActivityIds(exe.getId());
			activityIds.addAll(ids);
		}

		//获取流程图
		BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
		ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
		ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
		InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", activityIds, flows,
				engconf.getActivityFontName(), engconf.getLabelFontName(),
				engconf.getAnnotationFontName(), engconf.getClassLoader(), 1.0, true);
		OutputStream out = null;
		byte[] buf = new byte[1024];
		int legth = 0;
		try {
			out = httpServletResponse.getOutputStream();
			while ((legth = in.read(buf)) != -1) {
				out.write(buf, 0, legth);
			}
		} finally {
			if (in != null) {
				in.close();
			}
			if (out != null) {
				out.close();
			}
		}
	}
}
